<template>
  <div class="app-container page-container right-side-dialog">
    <!-- 搜索条件 -->
    <div class="header-search single_line">
      <el-form ref="search_form" :model="search" :inline="true" label-width="0">
        <div class="form-area">
          <div class="search_view">
            <el-form-item>
              <el-input v-model="search.docker_name" placeholder="请选择服务器" readonly @focus="serverVisible = true" />
            </el-form-item>
            <el-form-item>
              <el-input v-model="search.image_tags" placeholder="镜像名称" />
            </el-form-item>
            <div class="btn-area">
              <el-button type="success" size="mini" round @click="connectServer()">连接</el-button>
              <el-button type="danger" size="mini" round @click="disconnectServer()">断开</el-button>
              <el-button type="primary" size="mini" round @click="getPaginateData()">获取列表</el-button>
              <el-button size="mini" round @click="resetData()">重置</el-button>
            </div>
          </div>
        </div>
      </el-form>
    </div>
    <!-- 表格 -->
    <div class="content_view">
      <!-- 操作按鈕 -->
      <div class="main-header">
        <el-row :gutter="20">
          <el-col :span="4" class="left">镜像列表</el-col>
          <el-col :span="20" class="right">
            <el-button v-if="auth.search != -1" type="primary" size="mini" round @click="saveVisible()">新增</el-button>
          </el-col>
        </el-row>
      </div>
      <el-table ref="table" :data="paginate_data" :height="height-130" size="mini" strip>
        <el-table-column label="序号" type="index" width="60" />
        <el-table-column label="镜像ID" prop="image_id" min-width="250" align="left" show-overflow-tooltip />
        <el-table-column label="镜像名称" prop="image_tags[0]" min-width="200" align="left" show-overflow-tooltip />
        <el-table-column label="镜像大小" prop="image_size" min-width="100" align="left">
          <template slot-scope="scope">
            <div>{{ (scope.row.image_size/1024/1024).toFixed(2) }}M</div>
          </template>
        </el-table-column>
        <!-- <el-table-column label="创建时间" prop="create_time" min-width="150" align="left" /> -->
        <el-table-column label="操作" width="100" fixed="right" align="left">
          <template slot-scope="scope">
            <el-button v-if="auth.remove != -1" type="text" class="font_red" @click="deleteImage(scope.row.image_id,scope.row.image_tags[0])">删除</el-button>
            <el-button type="text" @click="detailImage(scope.row.image_tags[0])">详情</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <!-- 拉取镜像 -->
    <el-dialog title="拉取镜像" :visible.sync="editVisible" :close-on-click-modal="false" width="720px" @close='closePullImage'>
      <div class="searchImageName">
        <el-input
          v-model="search_image_name"
          placeholder="镜像名称"
          clearable
        />
        <div class="searchImageNameBut">
          <el-button type="primary" size="mini" icon="el-icon-search" round @click="searchImage()" />
        </div>
      </div>
      <el-scrollbar wrap-class="vertical_scrollbar" :style="{height: height + 'px'}">
        <el-table ref="table" :data="search_image_data" size="mini" strip>
          <el-table-column width="1" type="expand">
            <template slot-scope="props">
              <div id="pull_message" style="width:100%;height: 80px;overflow:auto" />
            </template>

          </el-table-column>
          <el-table-column label="序号" type="index" width="60" />
          <el-table-column label="镜像名称" prop="name" min-width="150" align="left" show-overflow-tooltip />
          <el-table-column label="收藏数量" prop="starCount" min-width="60" align="left" show-overflow-tooltip />
          <el-table-column label="镜像描述" prop="description" min-width="250" align="left" show-overflow-tooltip />
          <el-table-column label="操作" width="80" fixed="right" align="left">
            <template slot-scope="scope">
              <el-button v-if="auth.pull != -1 && search_image_data_index != (scope.$index+1)" type="text" @click="pullImage(scope.row.name,scope.row.description,scope)">拉取</el-button>
              <el-button v-if="auth.pull != -1 && search_image_data_index === (scope.$index+1)" class="font_red" type="text" @click="toogleExpand(scope,1)">收起</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-scrollbar>
    </el-dialog>
    <!-- 详情 -->
    <el-dialog title="镜像详情" :visible.sync="detailVisible" :close-on-click-modal="false" width="720px">
      <el-scrollbar wrap-class="vertical_scrollbar" :style="{height: height + 'px'}">
        <el-form ref="image_detail" label-width="20px" :model="image_detail">
          <el-row>
            <el-col>
              <el-form-item prop="note">
                <div class="form_lable">描述</div>
                <el-input v-model="image_detail.note" :disabled="true" type="textarea" :autosize="{ minRows: 1}" placeholder="" />
              </el-form-item>
            </el-col>
            <el-col>
              <el-form-item prop="image_name">
                <div class="form_lable">镜像名称</div>
                <el-input v-model="image_detail.image_name" :disabled="true" placeholder="" />
              </el-form-item>
            </el-col>
            <el-col>
              <el-form-item prop="docker_name">
                <div class="form_lable">服务器</div>
                <el-input v-model="image_detail.docker_name" :disabled="true" placeholder="" />
              </el-form-item>
            </el-col>
            <el-col>
              <el-form-item prop="create_time">
                <div class="form_lable">创建时间</div>
                <el-input v-model="image_detail.create_time" :disabled="true" placeholder="" />
              </el-form-item>
            </el-col>
            <el-col>
              <el-form-item prop="create_oper_name">
                <div class="form_lable">创建人员</div>
                <el-input v-model="image_detail.create_oper_name" :disabled="true" placeholder="" />
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </el-scrollbar>
    </el-dialog>
    <!-- 选择服务器 -->
    <el-dialog title="选择服务器" :visible.sync="serverVisible" :close-on-click-modal="false" width="720px" class="server_view">
      <el-scrollbar wrap-class="vertical_scrollbar" :style="{height: height + 'px'}">
        <SelectServer @selectServer="selectServer" />
      </el-scrollbar>
    </el-dialog>
  </div>
</template>
<script>
import { list, search, pull, remove, fremove , detail } from '@/api/pajx/server/image'
import { mapState } from 'vuex'
import SelectServer from '@/components/SelectServer'
import { basePostRequest,connect, disconnect } from '@/api/public'
import { formatDateTime , getUUID32 } from '@/utils/index'
import { getAppId, getSign , nowTime , getWebsocketURL } from '@/utils/auth'
export default {
  name: 'DockerServer',
  components: { SelectServer },
  data() {
    return {
      height: window.innerHeight - 135,
      auth: {},
      search: {},
      paginate_data: [],
      editVisible: false,
      detailVisible: false,
      search_image_name: '',
      search_image_data: [],
      serverVisible: false,
      search_image_data_index: '',
      webSocket_connect: null,
      webSocket_connect_key: '',
      image_detail: {
        docker_name: '',
        image_name: '',
        note: '',
        create_oper_name: '',
        create_time: ''
      }
    }
  },
  computed: {
    ...mapState({
      permission: state => state.permission.permission
    })
  },
  watch: {
  },
  beforeMount() {
    Object.assign(this.$data, this.$store.state.image.data)
  },
  beforeDestroy() {
    this.$store.commit('commitImageData', this.$data)
  },
  created() {
    this.permissionAuth()
  },
  methods: {
    // 获取按钮权限
    permissionAuth() {
      this.auth.search = this.permission.indexOf('/api/docker/image/search')
      this.auth.pull = this.permission.indexOf('/api/docker/image/pull')
      this.auth.remove = this.permission.indexOf('/api/docker/image/remove')
    },
    // 重置搜索选项
    resetData() {
      this.search = {}
    },
    // 选择服务器
    selectServer(data) {
      this.serverVisible = false
      this.search.server_id = data.server_id
      this.search.docker_name = data.docker_name
      // this.getPaginateData()
    },
    // 连接服务
    connectServer() {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      connect(this.search.server_id).then(response => {
        this.$notify({
          title: '成功',
          message: '连接成功',
          type: 'success'
        })
      })
    },
    // 断开服务
    disconnectServer() {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      disconnect(this.search.server_id).then(response => {
        this.$notify({
          title: '提示',
          message: '连接已断开',
          type: 'warning'
        })
      })
      this.paginate_data = []
    },
    // 获取列表
    getPaginateData() {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      list(this.search).then(response => {
        this.paginate_data = response.data
      })
    },
    // 打开新增页面
    saveVisible() {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      this.editVisible = true
    },
    // 搜索镜像
    searchImage() {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      if (!this.search_image_name) {
        this.$notify({
          title: '提示',
          message: '请输入镜像名称',
          type: 'warning'
        })
        return
      }
      search(this.search.server_id, this.search_image_name).then(res => {
        this.search_image_data = res.data
      })
    },
    // 拉取镜像
    pullImage(image_name, description, scope) {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      this.$confirm('确定拉取镜像？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.toogleExpand(scope, 0)// 展开显示面板
        if (!this.webSocket_connect_key) {
          this.webSocket_connect_key = 'image_pull:' + getUUID32()// 获取唯一连接键
        }
        this.websocketConnect()// 打开websocket连接
        if (!this.webSocket_connect || !this.webSocket_connect_key) {
          this.cmdInnerHtml('websocket未连接')
          return
        }
        basePostRequest('api/docker/image/pull', {
          server_id: this.search.server_id,
          image_name: image_name,
          note: description,
          connect_key: this.webSocket_connect_key
        }).then(res => {
          if (res.status === 200) {
            this.cmdInnerHtml('connecting,please wait...')
          } else {
            this.cmdInnerHtml(res.message)
          }
        })
      }).catch(() => {})
    },
    // 展开/收起
    toogleExpand(scope, flag) {
      if (flag === 0) {
        this.search_image_data_index = scope.$index + 1
      } else {
        this.search_image_data_index = ''
      }
      const $table = this.$refs.table
      this.search_image_data.map((item) => {
        if (scope.row.name != item.name) {
          $table.toggleRowExpansion(item, false)
        }
      })
      $table.toggleRowExpansion(scope.row)
    },
    // 向cmd添加内容并滚动至底部
    cmdInnerHtml(message) {
      this.$nextTick(() => {
        const span = document.createElement('p')
        span.style.margin = '2px 0'
        span.innerHTML = '-> ' + message
        const div = document.getElementById('pull_message')
        if (div) {
          div.appendChild(span)
          div.scrollTop = div.scrollHeight
        }
      })
    },
    //关闭拉取镜像侧滑
    closePullImage(){
      this.getPaginateData();
    },
    // 删除镜像
    deleteImage(image_id, image_tag) {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      this.$confirm('删除镜像 ' + image_tag + ' ?', '', {
          distinguishCancelAndClose: true,
          confirmButtonText: '删除',
          cancelButtonText: '强制删除'
        }).then(() => {
            remove(this.search.server_id, image_id, image_tag).then(res => {
              this.$message({
                message: '操作成功',
                type: 'success'
              })
              this.getPaginateData()
            })
          })
          .catch(action => {
            if(action === 'cancel'){
              this.$confirm('强制删除镜像 ' + image_tag + ' ?', '警告', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
              }).then(() => {
                fremove(this.search.server_id, image_id, image_tag).then(res => {
                  this.$message({
                    message: '操作成功',
                    type: 'success'
                  })
                  this.getPaginateData()
                })
              }).catch(() => {})
            }
          });
    },
    // 详情
    detailImage(image_name) {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      detail(this.search.server_id, image_name).then(res => {
        this.detailVisible = true
        this.image_detail.note = res.data.note
        this.image_detail.image_name = res.data.image_name
        this.image_detail.docker_name = res.data.docker_name
        this.image_detail.create_time = res.data.create_time ? formatDateTime(res.data.create_time) : '--'
        this.image_detail.create_oper_name = res.data.create_oper_name
      })
    },
    // 打开websocket连接
    websocketConnect() {
      // 判断当前浏览器是否支持WebSocket
      if ('WebSocket' in window) {
        var param = {};
        param['app_id'] = getAppId();
        param['connect_key'] = this.webSocket_connect_key;
        param['timestamp'] = nowTime();
        var api = getWebsocketURL() + "/websocket/image/pull" +
                  "?app_id=" + param.app_id +
                  "&connect_key=" + param.connect_key +
                  "&timestamp=" + param.timestamp +
                  "&sign="+getSign(param);
        this.webSocket_connect = new WebSocket(api);
      } else {
        console.log('当前浏览器不支持websocket');
        this.cmdInnerHtml('no websocket in window')
        return ;
      }
      // 监听窗口关闭事件，当窗口关闭时，主动去关闭websocket连接，防止连接还没断开就关闭窗口，server端会抛异常。
      window.onbeforeunload = this.closeWebSocket

      // 连接发生错误的回调方法
      this.webSocket_connect.onerror = this.websocketConnectOnerror

      // 连接成功建立的回调方法
      this.webSocket_connect.onopen = this.websocketConnectOnopen

      // 接收到消息的回调方法
      this.webSocket_connect.onmessage = this.websocketOnmessage

      // 连接关闭的回调方法
      this.webSocket_connect.onclose = this.websocketOnclose
    },
    //websocket关闭
    websocketOnclose(e){
      this.websocket_connect = null;
      this.webSocket_connect_key = '';
      this.cmdInnerHtml('websocket onclose');

    },
    // websocket收到消息
    websocketOnmessage(e) {
      var res = JSON.parse(e.data)
      if (res.cmd === 'image_pull_response') {
        this.cmdInnerHtml(res.data)
      }
    },
    //websocket连接打开
    websocketConnectOnopen(e){
      console.log("websocket onopen");
    },
    //websocket连接错误
    websocketConnectOnerror(e){
      console.log("websocket onerror");
      console.log(e);
      this.cmdInnerHtml('websocket onerror');
      this.websocket_connect = null;
      this.webSocket_connect_key = '';
    },
    // 关闭WebSocket连接
    closeWebSocket() {
      if(!this.webSocket_connect){
        console.log('websocket not connect');
        return;
      }
      this.webSocket_connect.close();
      this.cmdInnerHtml('websocket closed');
      this.websocket_connect = null;
      this.webSocket_connect_key = '';
    },
    // 发送消息
    send(message) {
      if(!this.webSocket_connect){
        console.log('websocket not connect');
        return;
      }
      this.webSocket_connect.send(message)
    }
  }
}
</script>
<style lang="scss">

.font_red{
  color: #FF5722;
}

 .searchImageName{
    position: absolute;
    left: 150px;
    top: 6px;
    width: 300px;
  }

  .searchImageNameBut{
    position: absolute;
    left: 315px;
    top: 5px;
  }

  .el-textarea.is-disabled .el-textarea__inner {
    background-color: white;
    border-color: #dfe4ed;
    color:#313233;
    cursor: not-allowed;
  }

  .el-input.is-disabled .el-input__inner {
    background-color: white;
    border-color: #dfe4ed;
    color: #313233;
    cursor: not-allowed;
  }

  .el-table__expand-column .cell{
    display:none;
  }

  .el-table__expanded-cell{
    background-color: black;
    color: #fff;
    height:80px;
  }

  .el-table__expanded-cell:hover{
    background-color: black !important;
  }

  .el-table__expanded-cell .el-form-item__content{
    font-size:0.5rem;
  }

</style>
